package cn.outsourcing.supermarket.common.utils;

import cn.outsourcing.supermarket.common.constants.CommonConstants;
import com.alibaba.druid.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 枚举处理工具类
 *
 * @author gzkemays
 * @since 2021/10/13 11:48
 */
@Slf4j
@SuppressWarnings("rawtypes")
public class EnumsOperaUtils {
  /** {@link Enum} 自带的 value */
  private static final String ENUM_DEFAULT_EXT_ARG = "$VALUES";
  /** getter 方法的头部 */
  private static final String GETTER_METHOD_PREFIX = "get";

  /**
   * 将指定枚举参数的 URL 可替换数值进行替换并返回最终替换结果
   *
   * <p>获取枚举的属性时要注意必须是以 get 驼峰的值进行获取。无必要时可以通过 {@link lombok.Lombok} 的 @Data 去定义 Getter 方法
   *
   * <p>params 替换的参数要确保 enums 中 args 是以 {@link CommonConstants#COMMA_SEPARATOR} 分割
   *
   * @param enums 指定枚举参数
   * @param params 替换参数对象
   * @return {@code String} 最终 GET 请求的地址结果
   */
  public static String parseUrlAndArgsEnums(
      Enum<? extends Enum<?>> enums, Map<String, String> params) {
    String url = "";
    Class<? extends Enum> clazz = enums.getClass();
    List<String> fieldNames = getFilterEnumsFields(clazz);
    try {
      List<String> replaces = new ArrayList<>();
      for (String fieldName : fieldNames) {
        Method getter = clazz.getMethod(GETTER_METHOD_PREFIX + fieldName);
        String value = String.valueOf(getter.invoke(enums));
        if (value.contains(CommonConstants.HTTPS_HEADER)) {
          url = value;
        } else if (value.contains(CommonConstants.COMMA_SEPARATOR)) {
          replaces = Arrays.asList(value.split(CommonConstants.COMMA_SEPARATOR));
        }
      }
      if (!StringUtils.isEmpty(url)) {
        for (String replace : replaces) {
          url = url.replace(replace, replace.toUpperCase());
        }
        for (Map.Entry<String, String> entry : params.entrySet()) {
          String key = entry.getKey().toUpperCase();
          if (url.contains(key)) {
            url = url.replace(key, entry.getValue());
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return url;
  }

  /**
   * 过滤获取 enums 指定参数
   *
   * @param enumsClazz enums 运行时的类
   * @return enums 的包含字段
   */
  private static List<String> getFilterEnumsFields(Class<? extends Enum> enumsClazz) {
    Field[] fields = enumsClazz.getDeclaredFields();
    Enum[] constants = enumsClazz.getEnumConstants();
    List<String> constantsList =
        Arrays.stream(constants).map(Enum::name).collect(Collectors.toList());
    return Arrays.stream(fields)
        .map(Field::getName)
        .filter(field -> !constantsList.contains(field) && !field.equals(ENUM_DEFAULT_EXT_ARG))
        .map(field -> field = StrUtils.getFirstUpperStr(field))
        .collect(Collectors.toList());
  }
}
